package pro.seac.twitter.application;

import static org.apache.commons.collections.CollectionUtils.isEmpty;
import static org.apache.commons.lang3.StringUtils.isBlank;

import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pro.seac.twitter.application.dao.MessageDao;
import pro.seac.twitter.application.dao.UserAccountDao;
import pro.seac.twitter.application.dto.MessageData;
import pro.seac.twitter.domain.Message;
import pro.seac.twitter.domain.UserAccount;

@Service
public class MessageService {
	private final static String USER_PATTERN = "([@]{1}[a-z0-9_-]{3,15})";
	public static final int MAX_MESSAGE_LENGTH = 150;
	@Autowired
	private UserAccountDao userAccountDao;
	@Autowired
	private MessageDao messageDao;

	/* *** commands * */
	@Transactional
	public Integer publishMessage(Integer senderId, String messageText) {
		if (isBlank(messageText) || messageText.length() > MAX_MESSAGE_LENGTH) { throw new IllegalArgumentException("message length 1-" + MAX_MESSAGE_LENGTH); }
		Message message = new Message();
		message.setContent(messageText);
		message.setSender(userAccountDao.findOne(senderId));
		processMessage(message);
		message.beforePersist();
		messageDao.save(message);
		return message.getId();
	}

	// TODO Algorytm parsujacy wydzielic dla latwiejszego testowania, na chwile obecna zostaje w serwisie
	protected void processMessage(Message message) {
		Matcher m = Pattern.compile(USER_PATTERN).matcher(message.getContent());
		while (m.find()) {
			handleMentionedUser(message, m.start(), m.end(), m.group(1));
		}
	}

	protected void handleMentionedUser(Message message, int startPosition, int endPosition, String userNameWithAt) {
		UserAccount user = userAccountDao.findByUserName(userNameWithAt.substring(1).toLowerCase());
		if (startPosition == 0 && user != null) message.setAddressee(user);
		if (user != null) message.addMentioned(user);
	}

	/* *** queries * */

	@Transactional(readOnly = true)
	public List<MessageData> getUserHomeFeedMessages(Integer userId) {
		List<Integer> followedIds = userAccountDao.getFollowedIdsById(userId);
		List<MessageData> list = messageDao.getUserMessages(userId, followedIds);
		return isEmpty(list) ? Collections.<MessageData> emptyList() : list;
	}

	@Transactional(readOnly = true)
	public List<MessageData> getUserProfileFeedMessages(Integer senderId) {
		List<MessageData> list = messageDao.getPublicBySender(senderId);
		return isEmpty(list) ? Collections.<MessageData> emptyList() : list;
	}

	@Transactional(readOnly = true)
	public List<MessageData> getUserMentionedFeedMessages(Integer mentionedUserId) {
		List<MessageData> list = messageDao.getUserMentioned(mentionedUserId);
		return isEmpty(list) ? Collections.<MessageData> emptyList() : list;
	}

	@Transactional(readOnly = true)
	public List<MessageData> getPublicFeedMessages() {
		List<MessageData> list = messageDao.getPublicMessage();
		return isEmpty(list) ? Collections.<MessageData> emptyList() : list;
	}

}
